package com.unitd.springboot.starter.mybatis;

import com.unitd.frame.mybatis.datasource.MutiRouteDataSource;
import com.unitd.frame.mybatis.parser.EntityInfo;
import com.unitd.frame.mybatis.parser.MybatisMapperParser;
import com.unitd.frame.mybatis.plugin.MybatisPluginInterceptor;
import com.unitd.frame.mybatis.plugin.PluginConstant;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import tk.mybatis.mapper.entity.Config;
import tk.mybatis.mapper.mapperhelper.MapperHelper;

import java.util.List;
import java.util.Properties;

/**
 * @desc 指定frame-mybatis中 自动分库、自动缓存、自动分页功能拦截器功能注入
 * @filename MybatisConfiguration.java
 * @copyright www.unitd.com
 * @author Hudan
 * @version 1.0
 * @date 2017/12/23
 */
@Configuration
@EnableConfigurationProperties(MybatisPluginProperties.class)
@ConditionalOnClass(MutiRouteDataSource.class)
@AutoConfigureAfter(MybatisAutoConfiguration.class)
public class MybatisConfiguration implements InitializingBean {

	/** Mybatis的数据操作柄 */
	@Autowired
	private SqlSessionFactory sqlSessionFactory;
	@Autowired
	private MybatisPluginProperties properties;

	/** 通过注解读取SpringBoot的配置中指定的mybatis的mapper文件*/
	@Value("${mybatis.mapper-locations}")
	private String mapperLocations;

	/**
	 * @desc 实现InitializingBean接口, 重写读取properties属性文件后的处理方法
	 * 此方法主要用于将frame-mybatis工程中实现的自动缓存、分页、读写分离等特性功能与springboot实现集成,启用对应的拦截器
	 */
	@Override
	public void afterPropertiesSet() {
		String interceptorHandlers = null;
		if (properties.isCacheEnabled()) {
			interceptorHandlers = "cache";
		}

		if (properties.isRwRouteEnabled()) {
			interceptorHandlers = interceptorHandlers == null ? "rwRoute" : interceptorHandlers + ",rwRoute";
		}

		if (properties.isDbShardEnabled()) {
			interceptorHandlers = interceptorHandlers == null ? "dbShard" : interceptorHandlers + ",dbShard";
		}

		if (properties.isPaginationEnabled()) {
			interceptorHandlers = interceptorHandlers == null ? "page" : interceptorHandlers + ",page";
		}

		if (interceptorHandlers != null) {
			MybatisPluginInterceptor interceptor = new MybatisPluginInterceptor();
			interceptor.setMapperLocations(mapperLocations);
			interceptor.setInterceptorHandlers(interceptorHandlers);
			sqlSessionFactory.getConfiguration().addInterceptor(interceptor);

			Properties p = new Properties();
			p.setProperty(PluginConstant.DB_TYPE, properties.getDbType());
			p.setProperty(PluginConstant.CRUD_DRIVER, properties.getCrudDriver());
			p.setProperty(PluginConstant.CACHE_NULL_VALUE, String.valueOf(properties.isNullValueCache()));
			p.setProperty(PluginConstant.CACHE_EXPIRE_SECONDS, String.valueOf(properties.getCacheExpireSeconds()));
			p.setProperty(PluginConstant.CACHE_DYNAMIC_EXPIRE, String.valueOf(properties.isDynamicExpire()));

			interceptor.setProperties(p);
			interceptor.afterPropertiesSet();
		} else {
			MybatisMapperParser.setMapperLocations(mapperLocations);
		}

		/* 设置tk.mapper的一些策略信息 */
		MapperHelper mapperHelper = new MapperHelper();
		Config config = new Config();
		config.setNotEmpty(false);
		// 主键UUID回写方法执行顺序,默认AFTER,可选值为(BEFORE|AFTER)
		config.setOrder("BEFORE");
//		// 设置默认的主键生成策略
//		config.setIDENTITY("SELECT REPLACE(UUID(),''-'','''')");
		mapperHelper.setConfig(config);
		List<EntityInfo> entityInfos = MybatisMapperParser.getEntityInfos();
		for (EntityInfo entityInfo : entityInfos) {
			mapperHelper.registerMapper(entityInfo.getMapperClass());
		}

		mapperHelper.processConfiguration(sqlSessionFactory.getConfiguration());
	}
}